home *** CD-ROM | disk | FTP | other *** search
/ Just Call Me Internet / Just Call Me Internet.iso / prog / atari / c / nos042_s / tipmail.c < prev    next >
C/C++ Source or Header  |  1994-09-16  |  7KB  |  342 lines

  1. /* "Dumb terminal" mailbox interface
  2.  * Copyright 1991 Phil Karn, KA9Q
  3.  *
  4.  *    May '91    Bill Simpson
  5.  *        move to separate file for compilation & linking
  6.  *    Sep '91 Bill Simpson
  7.  *        minor changes for DTR & RLSD
  8.  *
  9.  * ATARI Version by David Nash - dnash@chaos.demon.co.uk
  10.  *
  11.  *        __stdargs tip_in
  12.  *        Include st_asy.h in place of 8250.h
  13.  */
  14. #include "global.h"
  15. #include "mbuf.h"
  16. #include "timer.h"
  17. #include "proc.h"
  18. #include "iface.h"
  19. #ifdef    ATARI
  20. #include "st_asy.h"
  21. #else
  22. #include "8250.h"
  23. #endif
  24. #include "asy.h"
  25. #include "socket.h"
  26. #include "usock.h"
  27. #include "telnet.h"
  28. #include "mailbox.h"
  29. #include "tipmail.h"
  30. #include "devparam.h"
  31.  
  32. static struct tipcb {
  33.     struct tipcb *next;
  34.     struct proc *proc;
  35.     struct proc *in;
  36.     struct iface *iface;
  37.     int (*rawsave) __ARGS((struct iface *,struct mbuf *));
  38.     int s;
  39.     int echo;
  40.     struct timer timer;
  41. } *Tiplist;
  42. #define    NULLTIP    (struct tipcb *)0
  43.  
  44. static void __stdargs tip_in __ARGS((int dev,void *n1,void *n2));
  45. static void tipidle __ARGS((void *t));
  46.  
  47. unsigned Tiptimeout = 180;    /* Default tip inactivity timeout (seconds) */
  48.  
  49. /* Input process */
  50.  
  51. static void __stdargs tip_in(dev,n1,n2)
  52. int dev;
  53. void *n1,*n2;
  54. {
  55.     struct tipcb *tip;
  56.     struct mbuf *bp;
  57.     char *buf[2], line[MBXLINE];
  58.     int c, ret, pos = 0;
  59.  
  60.     tip = (struct tipcb *) n1;
  61.     while((c = get_asy(dev)) != -1){
  62.         Asy[dev].iface->lastrecv = secclock();
  63.         c &= 0x7f;
  64.         ret = 0;
  65.         if(tip->echo == WONT){
  66.             switch(c){
  67.             case 18:    /* CTRL-R */
  68.                 bp = pushdown(qdata(line,pos),4);
  69.                 memcpy(bp->data,"^R\r\n",4);
  70.                 ret = 1;
  71.                 break;
  72.             case 0x7f:    /* DEL */
  73.             case '\b':
  74.                 bp = NULLBUF;
  75.                 if(pos){
  76.                     --pos;
  77.                     bp = qdata("\b \b",3);
  78.                 }
  79.                 ret = 1;
  80.                 break;
  81.             case '\r':
  82.                 c = '\n';    /* CR => NL */
  83.             case '\n':
  84.                 bp = qdata("\r\n",2);
  85.                 break;
  86.             default:
  87.                 bp = pushdown(NULLBUF,1);
  88.                 *bp->data = c;
  89.                 break;
  90.             }
  91.             asy_send(dev,bp);
  92.             tip->iface->lastsent = secclock();
  93.             if(ret)
  94.                 continue;
  95.         }
  96.         line[pos++] = c;
  97.         if(pos == MBXLINE - 1 || tip->echo == WILL
  98.           || c == '\n'){
  99.             line[pos] = '\0';
  100.             pos = 0;
  101.             usputs(tip->s,line);
  102.             usflush(tip->s);
  103.         }
  104.     }
  105.     /* get_asy() failed, terminate */
  106.     close_s(tip->s);
  107.     tip->in = tip->proc;
  108.     tip->proc = Curproc;
  109.     buf[1] = Asy[dev].iface->name;
  110.     tip0(2,buf,NULL);
  111. }
  112. /* Start mailbox on serial line */
  113. int
  114. tipstart(argc,argv,p)
  115. int argc;
  116. char *argv[];
  117. void *p;
  118. {
  119.     register struct iface *ifp;
  120.     register struct asy *ap;
  121.     struct tipcb *tip;
  122.     struct mbuf *bp;
  123.     char *buf[2];
  124.     int dev, c, cmd, s[2], type = TIP;
  125.  
  126.     if((ifp = if_lookup(argv[1])) == NULLIF){
  127.         tprintf("Interface %s unknown\n",argv[1]);
  128.         return 1;
  129.     }
  130.     for(dev=0,ap = Asy;dev < ASY_MAX;dev++,ap++)
  131.         if(ap->iface == ifp)
  132.             break;
  133.     if(dev == ASY_MAX){
  134.         tprintf("Interface %s not asy port\n",argv[1]);
  135.         return 1;
  136.     }
  137.     if(ifp->raw == bitbucket){
  138.         tprintf("Tip session already active on %s\n",argv[1]);
  139.         return 1;
  140.     }
  141.     psignal(Curproc,0);    /* Don't keep the parser waiting */
  142.     chname(Curproc,"Mbox tip");
  143.     tip = (struct tipcb *) callocw(1,sizeof(struct tipcb));
  144.  
  145.     /* Save output handler and temporarily redirect output to null */
  146.     tip->rawsave = ifp->raw;
  147.     ifp->raw = bitbucket;
  148.     tip->iface = ifp;
  149.     tip->proc = Curproc;
  150.     tip->timer.func = tipidle;
  151.     tip->timer.arg = (void *) tip;
  152.     tip->next = Tiplist;
  153.     Tiplist = tip;
  154.     buf[1] = ifp->name;
  155.  
  156.     /* Suspend packet input drivers */
  157.     suspend(ifp->rxproc);
  158.  
  159.     for(;;) {
  160.         /* Wait for DCD to be asserted */
  161. #ifndef ATARI        
  162.         get_rlsd_asy(dev,MOVED_UP);
  163. #endif        
  164.  
  165.         if(socketpair(AF_LOCAL,SOCK_STREAM,0,s) == -1){
  166.             tprintf("Could not create socket pair, errno %d\n",errno);
  167.             tip0(2,buf,p);
  168.             return 1;
  169.         }
  170.         seteol(s[0],"\n");
  171.         seteol(s[1],"\n");
  172.         tip->echo = WONT;
  173.         tip->s = s[0];
  174.         newproc("mbx_incom",2048,mbx_incom,s[1],(void *)type,NULL,0);
  175.         set_timer(&tip->timer,Tiptimeout*1000);
  176.         start_timer(&tip->timer);
  177.         setflush(tip->s,-1);
  178.         sockmode(tip->s,SOCK_ASCII);
  179.  
  180.         /* Now fork into two paths, one rx, one tx */
  181.         tip->in = newproc("Mbox tip in",
  182.                 256,tip_in,dev,(void *)tip,NULL,0);
  183.         while((c = recvchar(tip->s)) != -1) {
  184.             if(c == IAC){    /* ignore most telnet options */
  185.                 if((cmd = recvchar(tip->s)) == -1)
  186.                     break;
  187.                 if(cmd > 250 && cmd < 255) {
  188.                     if((c = recvchar(tip->s)) == -1)
  189.                         break;
  190.                     switch(cmd){
  191.                     case WILL:
  192.                         if(c == TN_ECHO) {
  193.                             tip->echo = cmd;
  194.                             cmd = DO;
  195.                         }
  196.                         else
  197.                             cmd = DONT;
  198.                         break;
  199.                     case WONT:
  200.                         if(c == TN_ECHO)
  201.                             tip->echo = cmd;
  202.                         cmd = DONT;
  203.                         break;
  204.                     case DO:
  205.                     case DONT:
  206.                         cmd = WONT;
  207.                         break;
  208.                     }
  209.                     usprintf(tip->s,"%c%c%c",IAC,cmd,c);
  210.                     usflush(tip->s);
  211.                 }
  212.                 continue;
  213.             }
  214.             if(c == '\n')
  215.                 bp = qdata("\r\n",2);
  216.             else {
  217.                 bp = pushdown(NULLBUF,1);
  218.                 *bp->data = c;
  219.             }
  220.             asy_send(dev,bp);
  221.             ifp->lastsent = secclock();
  222.         }
  223.         close_s(tip->s);
  224.         killproc(tip->in);
  225.         tip->in = NULLPROC;
  226.         pwait(itop(s[1])); /* let mailbox terminate, if necessary */
  227.         stop_timer(&tip->timer);
  228.  
  229.         /* Tell line to go down */
  230.         ifp->ioctl(ifp,PARAM_DOWN,TRUE,0L);
  231.  
  232.         /* Wait for DCD to be dropped */
  233. #ifndef ATARI        
  234.         get_rlsd_asy(dev,MOVED_DOWN);
  235. #endif        
  236.     }
  237. }
  238. int
  239. tip0(argc,argv,p)
  240. int argc;
  241. char *argv[];
  242. void *p;
  243. {
  244.     register struct iface *ifp;
  245.     struct tipcb *tip, *prev = NULLTIP;
  246.     struct proc *proc;
  247.  
  248.     if((ifp = if_lookup(argv[1])) == NULLIF){
  249.         tprintf("Interface %s unknown\n",argv[1]);
  250.         return 1;
  251.     }
  252.     for(tip = Tiplist; tip != NULLTIP; prev = tip, tip = tip->next)
  253.         if(tip->iface == ifp) {
  254.             if(prev != NULLTIP)
  255.                 prev->next = tip->next;
  256.             else
  257.                 Tiplist = tip->next;
  258.             proc = tip->proc;
  259.             close_s(tip->s);
  260.             ifp->raw = tip->rawsave;
  261.             resume(ifp->rxproc);
  262.             stop_timer(&tip->timer);
  263.             killproc(tip->in);
  264.             free((char *)tip);
  265.             killproc(proc);
  266.             return 0;
  267.         }
  268.     return 0;
  269. }
  270. static void
  271. tipidle(t)
  272. void *t;
  273. {
  274.     struct tipcb *tip;
  275.     static char *msg = "You have been idle too long. Please hang up.\r\n";
  276.     tip = (struct tipcb *) t;
  277.     if(secclock() - tip->iface->lastrecv < Tiptimeout){
  278.         set_timer(&tip->timer,(Tiptimeout-secclock() *
  279.          tip->iface->lastrecv)*1000);
  280.         start_timer(&tip->timer);
  281.         return;
  282.     }
  283.     asy_send(tip->iface->dev,qdata(msg,strlen(msg)));
  284.     tip->iface->lastsent = secclock();
  285.     close_s(tip->s);
  286. }
  287.  
  288. static int Stelnet = -1;
  289.  
  290. /* Start up Telnet server */
  291. int
  292. telnet1(argc,argv,p)
  293. int argc;
  294. char *argv[];
  295. void *p;
  296. {
  297.     struct sockaddr_in lsocket;
  298.     int s;
  299.     int type;
  300.  
  301.     if(Stelnet != -1){
  302.         return 0;
  303.     }
  304.     psignal(Curproc,0);     /* Don't keep the parser waiting */
  305.     chname(Curproc,"Telnet listener");
  306.  
  307.     lsocket.sin_family = AF_INET;
  308.     lsocket.sin_addr.s_addr = INADDR_ANY;
  309.     if(argc < 2)
  310.         lsocket.sin_port = IPPORT_TELNET;
  311.     else
  312.         lsocket.sin_port = atoi(argv[1]);
  313.     Stelnet = socket(AF_INET,SOCK_STREAM,0);
  314.     bind(Stelnet,(char *)&lsocket,sizeof(lsocket));
  315.     listen(Stelnet,1);
  316.     for(;;){
  317.         if((s = accept(Stelnet,NULLCHAR,(int *)NULL)) == -1)
  318.             break;    /* Service is shutting down */
  319.  
  320.         if(availmem() < Memthresh){
  321.             shutdown(s,1);
  322.         } else {
  323.             /* Spawn a server */
  324.             type = TELNET;
  325.             newproc("mbox",2048,mbx_incom,s,(void *)type,NULL,0);
  326.         }
  327.     }
  328.     return 0;
  329. }
  330. /* Stop telnet server */
  331. int
  332. telnet0(argc,argv,p)
  333. int argc;
  334. char *argv[];
  335. void *p;
  336. {
  337.     close_s(Stelnet);
  338.     Stelnet = -1;
  339.     return 0;
  340. }
  341.  
  342.